home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / A / Arrange Developer Kit 1.0.sit / Examples / Reorder Viewsƒ / Reorder Views.cp < prev    next >
Encoding:
Text File  |  1994-07-22  |  10.2 KB  |  264 lines  |  [TEXT/KAHL]

  1. // Reorder Views Plugin
  2. // ©by Ben Weiss, 6/21/94
  3. // Show a menu item called 'Reorder Views' in the Views menu.  When selected, sort
  4. // the current topic's views alphabetically.
  5.  
  6. // Revision 1.1 6/22/94    Added code to count views in ATM & changed resource ids to -512
  7. // Revision 1.2 7/22/94 support Undo; messed with resource ID's
  8.  
  9. // To see all the arNoteID's & such,
  10. // go into the debug window & type i<noteid> & hit enter
  11. // (1000 decimal is id of root folder)
  12.  
  13. #include "ArrangeCallbacks.h"
  14. #include "PluginLibrary.h"
  15.  
  16. #include <Dialogs.h>                        // for my about box
  17.  
  18. // Remember that your moduleResourceID should be a negative multiple of 0x200 and must 
  19. // be registered with Common Knowledge, Inc.  Also, your ModuleID must be unique and
  20. // also registered with Common Knowledge, Inc.
  21. #define    moduleID            0x10000006        // my module ID is 0x10000006 "Reorder Views"
  22. #define    moduleResID            0xFFFF8000        // was -512 in v.1.1
  23. #define reorderViewCode     'bw a'
  24. #define aboutCode           'bw  '
  25.  
  26.  
  27.  
  28. class ReorderViews
  29.     {
  30. public:
  31.     ReorderViews(const ArrangeCallbackTbl* theCalls);
  32.     ~ReorderViews();
  33.     
  34.     arHookResult MenuNotify (Integer menuCode, Integer menuParam, pShort modifiers);
  35.     void AboutToMenu();
  36.     
  37. private:
  38.     const ArrangeCallbackTbl* calls; // callback table
  39.     
  40.     void DoIt();
  41.     };    //    ReorderViews
  42.  
  43.  
  44. /*************************************************************************/
  45. /**************************** Main entry point ***************************/
  46. /*************************************************************************/
  47.  
  48. /* Root entry point for the module - must be the first function in the
  49.  * file, so that the linker will place it first in the code segment.
  50.  */
  51. extern "C" Integer main (ModuleParamBlock *pb, ModuleRootAction action, Integer)
  52.     {
  53.     ArrangeCallbackTbl* calls = (ArrangeCallbackTbl*)(pb->calls);
  54.     
  55.     switch (action)
  56.         {
  57.         case mrLoad:
  58.             {
  59.             // Allocate memory and create a new OurPlugin object.
  60.             void* storage = calls->mem->AllocMem( sizeof(ReorderViews), amFreeStore | amErrIfNoMem );
  61.             pb->moduleRefcon = uInteger(new(storage) ReorderViews(calls));
  62.             return 1;
  63.             }
  64.         
  65.         case mrUnload:
  66.             {
  67.             // Dispose of the ReorderViews object
  68.             delete (ReorderViews*)(pb->moduleRefcon);
  69.             calls->mem->DeallocMem((void*)(pb->moduleRefcon), amFreeStore);
  70.             return 0;
  71.             }
  72.         default:
  73.             return 0;
  74.         
  75.         }    //    switch (action)
  76.     
  77.     }        //    main
  78.  
  79. static arHookResult OurMenuHook (ModuleParamBlock* pb, Integer menuCode, Integer menuParam, pShort modifiers ENDP)
  80.     {
  81.     return ((ReorderViews*)(pb->moduleRefcon))->MenuNotify (menuCode, menuParam, modifiers );
  82.     } // OurMenuHook
  83.  
  84.  
  85. void OurATMHook(ModuleParamBlock* pb ENDP)
  86.     {
  87.     ((ReorderViews*)(pb->moduleRefcon))->AboutToMenu();
  88.     } // OurATMHook
  89.  
  90.  
  91. //*************************************************************************
  92. //******************************* Entry Point *****************************
  93. //*************************************************************************
  94.  
  95. // Make an object.  This is called once, from the ModuleRoot function, 
  96. // when the module is initialized (i.e. at application boot time).
  97.  
  98. ReorderViews::ReorderViews (const ArrangeCallbackTbl* theCalls)
  99.     {
  100.     calls = theCalls;
  101.     
  102. //Add an item with the given name, command key (0 if none), command-code, and refcon
  103. //to the end of the menu with the given code.  By default the item will be enabled and unchecked.
  104. //If itemName is "-", then the item will be disabled and will be drawn as a gray bar.
  105. //No other Menu Manager metacharacters are supported.
  106.  
  107.     calls->ui->AddMenuItem (mTopics, "-", 0, 0, 0);    // a gray line
  108.     calls->ui->AddMenuItem (mTopics, "Reorder Views", 0, reorderViewCode, 0);
  109.     calls->ui->AddMenuItem (mPluginAbout, "About Reorder Views", 0, aboutCode, 0);
  110.     
  111. // Add or remove a hook from the menu item(s) with the given code.
  112. // If the code is nil, the hook will be notified whenever any menu item is chosen.
  113. // The hook function should return true if it handled the command, false if it did not.
  114. // If it returns false, control will pass to the next registered hook function for the menu item,
  115. // and eventually to the standard application code (if any).
  116.  
  117.     calls->ui->SetMenuHook (OurMenuHook, 0, true, reorderViewCode);
  118.     calls->ui->SetMenuHook (OurMenuHook, 0, true, aboutCode);
  119.     calls->ui->SetATMHook (OurATMHook,  0, true);    // ATM = About To Menu
  120.     } // ReorderViews constructor
  121.  
  122.  
  123. ReorderViews::~ReorderViews()    {}        //ReorderViews distructor; Dispose of a ReorderViews object.
  124.  
  125.  
  126. /* This function is called whenever the user chooses a menu item for which
  127.  * we have registered (via the SetMenuHook callback function).  It should
  128.  * return true if we handle the menu item ourselves, false to let the
  129.  * application process it.
  130.  */
  131. arHookResult ReorderViews::MenuNotify (Integer menuCode, Integer menuParam, pShort modifiers)
  132.     {
  133.     if (menuCode == reorderViewCode)
  134.         {
  135.         DoIt();
  136.         return true;
  137.         }
  138.     else if (menuCode == aboutCode)
  139.         {
  140.         Alert (moduleResID, nil);
  141.         return true;
  142.         }
  143.     else
  144.         return false;
  145.     
  146.     } // MenuNotify
  147.  
  148.  
  149. /* This function is called whenever the user clicks in the menu bar or types
  150.  * a command key, just before processing the event.  It does any fixing up
  151.  * of menus which might be necessary based on the current state of affairs.
  152.  * In our case, the only thing we do is disable our menu item if there is no
  153.  * open document window
  154.  */
  155.  
  156. void ReorderViews::AboutToMenu()
  157.     {
  158.     arWindowID currFrontWin = calls->sel->GetActiveWindow ();
  159.     if (currFrontWin == nil)    // no window -- dim the lamps
  160.         // void SetMenuItem( Short menuCode, Integer commandCode, Integer itemRefcon, 
  161.         // const char* itemName, Boolean itemEnabled, Short markChar, Short itemStyle );
  162.         // Set the title, enabled state, mark character, and style for the menu item with
  163.         // the given code and refcon.  If no such item exists, log an error.
  164.         // If itemName is nil, then the item's title is unchanged.
  165.         calls->ui->SetMenuItem (mTopics, reorderViewCode, 0, nil, false, 0, 0);
  166.     else
  167.         {    // Okay-- we have a window.  But are there any views?
  168.         pBoolean returnRoot = true;    /* will this alawys return a arTopicID? */
  169.         arTopicID thisTopic = calls->sysObj->GetCurrentTopic (currFrontWin, returnRoot);
  170.         arFieldID viewsField = calls->sysObj->GetBuiltInObject (boTopicViewsField);    
  171.         if (calls->data->GetFieldListLen (thisTopic, viewsField) < 2)
  172.             calls->ui->SetMenuItem (mTopics, reorderViewCode, 0, nil, false, 0, 0);    
  173.         else
  174.             calls->ui->SetMenuItem (mTopics, reorderViewCode, 0, nil, true, 0, 0);    
  175.         }
  176.     } // AboutToMenu
  177.  
  178.  
  179. void ReorderViews::DoIt()
  180.     {
  181.     //----------------------------------------
  182.     // Return the ID of the frontmost window for the current document.
  183.     // If the document has no open windows, return nil.
  184.     // Note that this function will return hoist windows as well as regular document windows.
  185.  
  186.     arWindowID currFrontWin = calls->sel->GetActiveWindow ();
  187.     if (currFrontWin)
  188.         {
  189.         // What do I do if the current window is a hoist window?
  190.     
  191.     
  192.         //----------------------------------------
  193.         // Return the ID of the current (selected) topic or folder in this window.
  194.         // If the window is showing a view, and returnRoot is false,
  195.         // then return the ID of the view itself; otherwise return the ID of its parent topic or folder.
  196.  
  197.         pBoolean returnRoot = true;    /* will this alawys return a arTopicID? */
  198.         arTopicID thisTopic = calls->sysObj->GetCurrentTopic (currFrontWin, returnRoot);
  199.     
  200.         //----------------------------------------
  201.         // Get the field ID of the field inside this note which has the view info in it.
  202.  
  203.         arFieldID viewsField = calls->sysObj->GetBuiltInObject (boTopicViewsField);    
  204.     
  205.         //----------------------------------------
  206.         // Put the views into a list object
  207.  
  208.         arListID myList;
  209.         myList = calls->data->GetFieldList (thisTopic, viewsField);
  210.     
  211.         //----------------------------------------
  212.         // Return a new list containing the same notes as the input list,
  213.         // but sorted according to the given sorting rule.
  214.         // The first clause has primary importance; subsequent clauses are used to break ties.
  215.         // If two notes tie on all clauses, the retain the same relative order as in the input list.
  216.         // Constants for the type field of an arSortClause record.
  217.  
  218.         arFieldID nameField;
  219.         nameField = calls->sysObj->GetBuiltInObject (boNameField);
  220.  
  221.         arSortClause mySortClause;
  222.         mySortClause.type = sAscending;
  223.          mySortClause.field = nameField;
  224.  
  225.         arListID mySortedList;
  226.         mySortedList = calls->search->SortNotes (myList, 1, &mySortClause);
  227.     
  228.         //----------------------------------------
  229.         /// void SetupUndo(const char* operationName, Boolean setChangedFlag);
  230.         /// Mark the beginning of an undoable operation with the given name.
  231.         /// That name (prefixed with the string “Undo ” or “Redo ”) will appear
  232.         /// in the Edit menu, and choosing it will cause the document to revert
  233.         /// to its state at the present moment.  If setChangedFlag is true, the
  234.         /// document will be marked as having unsaved changes (see the SetChangedFlag
  235.         /// function for details).  If you pass nil for the name parameter, then Undo
  236.         /// will be disabled (i.e. any existing undo state will be thrown away);
  237.         /// the setChangedFlag parameter is still respected in this case.
  238.         ///
  239.         /// You should generally make this call as late as possible in the execution
  240.         /// of a command, just before you start to actually change the state of the
  241.         /// document.  In particular, you should almost always call FlushSelection
  242.         /// before SetupUndo, and not call SetupUndo if FlushSelection returns false.
  243.         calls->doc->SetupUndo ("Reorder Views", true);
  244.  
  245.         //----------------------------------------
  246.         // Now put the newly sorted list into the note link field for views for this topic
  247.         // Overwrite the contents of a note-link field with a list of notes contained
  248.         // in a ListID; if the note doesn’t have this field, add it as an invisible field.
  249.         // If the field isn’t a note-link field, log an error and do nothing.
  250.         //
  251.         // If the sfDisableModDate flag is set, then don't update the note's modification
  252.         // date and last editor name.  A nil value for the list parameter is interpreted as
  253.         // the empty list.
  254.         //
  255.         // void SetFieldList( arNoteID note, arFieldID field, arListID list, arSetFieldFlags flags );
  256.  
  257.         calls->data->SetFieldList (thisTopic, viewsField, mySortedList, nullSFF);
  258.         calls->doc->SetChangedFlag();
  259.  
  260.         //----------------------------------------
  261.         calls->list->DisposeList (mySortedList);            // Get rid of the no longer needed list
  262.         calls->list->DisposeList (myList);
  263.         };    // if no current front window
  264.     }    //    ReorderViews::DoIt()